package com.gitee.huanminabc.jlambda_sql.segments;

import com.gitee.huanminabc.jlambda_sql.warapper.AbstractSqlWrapper;
import com.gitee.huanminabc.jlambda_sql.SQL;
import com.gitee.huanminabc.jlambda_sql.base.SqlFun;
import com.gitee.huanminabc.jlambda_sql.base.SqlPick;

import java.util.List;

/**
 * 特殊实现类
 * @param <T>
 * @param <Children>
 */
public abstract class SqlSpecialImplSegments<T, Children extends AbstractSqlWrapper<T, Children>>    extends AbstractSqlWrapper<T, Children> implements SqlSpecialSegments<Children> {
    public SqlSpecialImplSegments() {
    }
    public SqlSpecialImplSegments(Class<T> entityClass, SQL sql) {
        super(entityClass, sql);
    }

    public Children DISTINCT() {
        SQL().append(" DISTINCT ");
        return typedThis;
    }

    @Override
    public Children LEFT_BRACKET() {
        SQL().append(" ( ");
        return typedThis;
    }

    @Override
    public Children RIGHT_BRACKET() {
        SQL().append(" ) ");
        return typedThis;
    }

    @Override
    public Children COMMA() {
        SQL().append(" , ");
        return typedThis;
    }

    //加field  ,兼容多表查询 on
    //如果在使用field 之前没有加入对应的表,那么会自动加入主表
    public  <Y> Children FIELD(SqlFun<Y,?> column){
        getFunFieldName(column, sqlColumn -> {
            SQL().append(sqlColumn.getTableName()).append(".").append(sqlColumn.getColumnName()).append(" ");
        });
        return typedThis;
    }

    @Override
    public <Y> Children FIELD(String column) {
        SQL().append(column).append(" ");
        return typedThis;
    }

    //列 全部满足条件的字段
    @Override
    public Children S_COLUMN() {
        List<String> columnAll = getColumnAll();
        for (String column : columnAll) {
            SQL().addSelectColumn(getTableInfo().getAlias(),column);
        }
        return typedThis;
    }
    public Children S_COLUMN_CUSTOM(String sql){
        SQL().addSelectColumn(sql);
        return typedThis;
    }
    public  Children S_COLUMN_CUSTOM(SqlFun<Children, Children> sql, String alias){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();
        string=string.trim();
        string="("+string+")";
        SQL().addSelectColumnAlias(string,alias);
        return typedThis;
    }


    //单表多个自选字段  ,不兼容多个不同类型的实体类
    public  <Y>  Children S_COLUMN(SqlFun<Y,?>... columns){
        //不能传空
        if(columns==null||columns.length==0){
            throw new RuntimeException("S_COLUMN方法参数不能为空");
        }
        for (SqlFun<Y,?> column : columns) {
            getFunFieldName(column, sqlColumn -> {
                SQL().addSelectColumn(sqlColumn.getTableName(),sqlColumn.getColumnName());
            });
        }
        return typedThis;
    }

    public   Children S_COLUMNS(SqlPick<?,?>... columns){
        //不能传空
        if(columns==null||columns.length==0){
            throw new RuntimeException("S_COLUMNS方法参数不能为空");
        }
        for (SqlPick<?,?> column : columns) {
            getFunFieldName( column.getFunction(), sqlColumn -> {
                SQL().addSelectColumn(sqlColumn.getTableName(),sqlColumn.getColumnName());
            });
        }
        return typedThis;
    }
    //单表单个自选字段 ,或者多表单个字段  ,如果存在多表字段,那么需要在主表中加入额外的字段用于接收数据
    public  <Y> Children S_COLUMN(SqlFun<Y,?> column){
        getFunFieldName(column, sqlColumn -> SQL().addSelectColumn(sqlColumn.getTableName(),sqlColumn.getColumnName()));
        return typedThis;
    }
    public  <Y> Children S_COLUMN(SqlFun<Y, ?> column,String alias){
        getFunFieldName(column, sqlColumn -> SQL().addSelectColumn(sqlColumn.getTableName(),sqlColumn.getColumnName(),alias));
        return typedThis;
    }


    public Children ASC(){
        SQL().append(" ASC ").append("\n");
        return typedThis;
    }

    public Children DESC(){
        SQL().append(" DESC ").append("\n");
        return typedThis;
    }


    @Override
    public Children CUSTOM(String sql) {
        SQL().append(sql);
        return typedThis;
    }
}
